package com.tange.ai.core.sample.play

import android.Manifest
import android.content.Context
import android.content.Intent
import android.content.pm.ActivityInfo
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.graphics.Color
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Environment
import android.view.Gravity
import android.view.KeyEvent
import android.view.View
import android.widget.FrameLayout
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import com.tange.ai.core.sample.R
import com.tange.ai.core.sample.utils.Utils
import com.tange.ai.core.sample.databinding.ActivityDeviceLiveBinding
import com.tange.base.toolkit.*
import com.tange.core.device.facade.DeviceFacade
import com.tange.core.device.facade.Instruction
import com.tange.core.device.facade.Status
import com.tange.core.device.talk.DeviceTalkback
import com.tange.core.media.render.DeviceMediaRender
import com.tange.core.media.source.impl.live.DeviceLiveMediaSource
import com.tange.module.media.play.util.BitmapUtil
import com.tg.appcommon.android.Packet
import com.tg.appcommon.android.TGLog
import java.io.File

class DeviceLiveActivity : AppCompatActivity() {

    companion object {
        private const val TAG = "DeviceLiveActivity_"
        private const val PARAM_DEVICE_ID = "PARAM_DEVICE_ID"
        private const val INSTRUCTION_DEV_INFO_REQ = 0x0330
        private const val INSTRUCTION_DEV_INFO_RESP = 0x0331

        fun launch(context: Context, deviceId: String) {
            context.startActivity(Intent(context, DeviceLiveActivity::class.java).apply {
                putExtra(PARAM_DEVICE_ID, deviceId)
            })
        }
    }

    private var albumPath = Environment.getExternalStorageDirectory()
        .toString() + File.separator + Environment.DIRECTORY_DCIM

    private lateinit var deviceId: String

    private lateinit var binding: ActivityDeviceLiveBinding

    private lateinit var deviceFacade: DeviceFacade
    private lateinit var deviceLiveMediaSource: DeviceLiveMediaSource
    private lateinit var deviceMediaRender: DeviceMediaRender

    private var deviceTalkback: DeviceTalkback? = null
    private var isLandscape = false
    private var rendered = false
    private var hasSdCard = false

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityDeviceLiveBinding.inflate(layoutInflater).apply {
            setContentView(root)
            supportActionBar?.hide()
            Utils.setDarkStatusBar(this@DeviceLiveActivity, Color.TRANSPARENT)
        }

        deviceId = intent.getStringExtra(PARAM_DEVICE_ID)

        // 创建设备交互模块
        deviceFacade = DeviceFacade(deviceId).apply {

            // 监听连接状态变化
            observeConnectStatus {
                TGLog.i(TAG, "[connect-status] ${it.status}")
                ui {
                    if (it.status != Status.SUCCESS) {
                        if (it.status == Status.FAILED) {
                            binding.loading.gone()
                            binding.connect.visible()
                            binding.connect.text = "重试"
                            Tips.show("连接失败：$it")
                        } else {
                            binding.loading.visible()
                        }
                    } else {
                        if (rendered) {
                            binding.loading.gone()
                        }

                        deviceFacade.instruct.send(Instruction(INSTRUCTION_DEV_INFO_REQ))
                    }
                }
            }
        }

        // 监听设备端命令相应
        deviceFacade.instruct.observeOnReceive {
            if (it.id == INSTRUCTION_DEV_INFO_RESP) {
                it.data?.let {
                    val totalSize = Packet.byteArrayToInt_Little(it, 40)
                    hasSdCard = totalSize > 0
                }
            }
        }

        // 创建实时媒体数据源
        deviceLiveMediaSource = DeviceLiveMediaSource(deviceFacade)

        // 创建媒体播放器
        deviceMediaRender = DeviceMediaRender(this, deviceLiveMediaSource).apply {

            // 将播放器示例绑定到UI上
            attach(binding.playerContainer, createCenterLayoutParams())

            // 监听首帧数据渲染回调
            observeFirstFrameRendered {
                TGLog.i(TAG, "[first-rendered] ")
                rendered = true
                binding.loading.gone()
            }
        }


        binding.loading.visible()
        binding.audio.setImageDrawable(ContextCompat.getDrawable(this,
            R.drawable.ic_baseline_volume_off_24
        ))
        binding.audio.onClicked { switchAudio() }
        binding.screenShot.onClicked { screenshot() }
        binding.screenRecord.onClicked { screenRecord() }
        binding.talkBack.onClicked { talkback() }
        binding.fullScreen.onClicked { switchFullScreen() }
        binding.back.onClicked { finish() }
        binding.connect.onClicked { deviceLiveMediaSource.enableVideoProduce(true) }
        binding.localPlayback.onClicked { launchLocalPlayback() }
        binding.cloudPlayback.onClicked { launchCloudPlayback() }
    }

    private fun launchLocalPlayback() {
        if (!hasSdCard) {
            Tips.show("无SD卡！")
            return
        }

        DevicePlaybackActivity.launch(this, deviceId)
    }

    private fun launchCloudPlayback() {
        CloudPlaybackActivity.launch(this, deviceId)
    }

    override fun onResume() {
        super.onResume()
        TGLog.i(TAG, "[onResume] ")
        deviceLiveMediaSource.enableVideoProduce(true)
        deviceMediaRender.enableVideoRender(true)
    }

    override fun onPause() {
        super.onPause()
        TGLog.i(TAG, "[onPause] ")
        deviceLiveMediaSource.enableVideoProduce(false)
        deviceLiveMediaSource.enableAudioProduce(false)
        deviceMediaRender.enableAudioRender(false)
        deviceMediaRender.enableVideoRender(false)
        binding.audio.setImageDrawable(ContextCompat.getDrawable(this,
            R.drawable.ic_baseline_volume_off_24
        ))
    }

    override fun onDestroy() {
        super.onDestroy()
        deviceFacade.disconnect()
    }

    private fun createCenterLayoutParams() = FrameLayout.LayoutParams(
        FrameLayout.LayoutParams.MATCH_PARENT,
        FrameLayout.LayoutParams.MATCH_PARENT
    ).apply { gravity = Gravity.CENTER }

    private fun talkback() {

        if (!deviceFacade.connected()) {
            Tips.show("等设备连接成功后，再使用对讲")
            return
        }

        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                this.requestPermissions(arrayOf(Manifest.permission.RECORD_AUDIO), 100)
            }
            Tips.show("需要录音权限")
            return
        }

        if (deviceTalkback == null) {
            deviceTalkback = DeviceTalkback(facade = deviceFacade).apply {
                observeStatus {
                    ui {
                        if (it.success) {
                            if (deviceLiveMediaSource.isAudioProduceEnabled()) {
                                Tips.show("对讲开启成功，设备音频关闭")
                                switchAudio()
                            } else {
                                Tips.show("对讲开启成功")
                            }
                            binding.talkBack.setImageDrawable(ContextCompat.getDrawable(this@DeviceLiveActivity,
                                R.drawable.ic_baseline_mic_on_24
                            ))
                        } else {
                            Tips.show("对讲开启失败：$it")
                            binding.talkBack.setImageDrawable(ContextCompat.getDrawable(this@DeviceLiveActivity,
                                R.drawable.ic_baseline_mic_off_24
                            ))
                        }
                    }
                }
            }
        }

        if (deviceTalkback?.started == true) {
            deviceTalkback?.stop()
            binding.talkBack.setImageDrawable(ContextCompat.getDrawable(this,
                R.drawable.ic_baseline_mic_off_24
            ))
        } else {
            deviceTalkback?.start()
        }
    }

    private fun screenRecord() {
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                this.requestPermissions(arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), 100)
            }
            Tips.show("需要存储权限")
            return
        }

        if (deviceMediaRender.screenRecord().isStarted()) {
            val file = File(albumPath, "TG-${System.currentTimeMillis()}.mp4")
            deviceMediaRender.screenRecord().finish(file.absolutePath) {
                if (it) Tips.show("录屏已保存到 ${file.absolutePath}")
            }
            binding.screenRecord.setImageDrawable(ContextCompat.getDrawable(this,
                R.drawable.ic_baseline_videocam_24
            ))
        } else {
            deviceMediaRender.screenRecord().start()
            binding.screenRecord.setImageDrawable(ContextCompat.getDrawable(this,
                R.drawable.ic_baseline_videocam_off_24
            ))
            Tips.show("开始录屏，再次点击结束录屏")
        }
    }

    private fun switchAudio() {
        if (deviceLiveMediaSource.isAudioProduceEnabled()) {
            binding.audio.setImageDrawable(
                ContextCompat.getDrawable(this, R.drawable.ic_baseline_volume_off_24)
            )
            deviceLiveMediaSource.enableAudioProduce(false)
            deviceMediaRender.enableAudioRender(false)
        } else {
            binding.audio.setImageDrawable(
                ContextCompat.getDrawable(
                    this,
                    R.drawable.ic_baseline_volume_on_24
                )
            )
            deviceLiveMediaSource.enableAudioProduce(true)
            deviceMediaRender.enableAudioRender(true)
        }
    }

    private fun screenshot() {
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                this.requestPermissions(arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), 100)
            }
            Tips.show("需要存储权限")
            return
        }

        deviceMediaRender.screenshot()?.let {

            val file = File(albumPath, "TG-${System.currentTimeMillis()}.jpg")

            BitmapUtil.saveBitmapToFile(file, it, Bitmap.CompressFormat.JPEG)

            if (file.exists()) {
                val intent = Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE)
                val uri = Uri.fromFile(file)
                intent.data = uri
                sendBroadcast(intent)
                Tips.show("截图已保存到 ${file.absolutePath}")
            }
        }
    }

    private fun switchFullScreen() {
        if (isLandscape) {
            binding.bottomLayout.visibility = View.VISIBLE
            binding.topBar.visibility = View.VISIBLE
            binding.opButtons.visibility = View.VISIBLE
            requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
            isLandscape = false
        } else {
            binding.bottomLayout.visibility = View.GONE
            binding.topBar.visibility = View.GONE
            binding.opButtons.visibility = View.GONE
            requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
            isLandscape = true
            binding.playerContainer.postDelayed({
                Tips.show("使用物理返回键退出全屏")
            }, 1000)
        }

        binding.playerContainer.post {
            deviceMediaRender.resize()
        }
    }

    override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean =
        if (KeyEvent.KEYCODE_BACK == keyCode) {
            if (isLandscape) {
                switchFullScreen()
                true
            }
            else {
                finish()
                true
            }
        } else super.onKeyDown(keyCode, event)
}